//
//  YMPDFObject.m
//  TestDemo
//
//  Created by fantasy on 16/6/26.
//  Copyright © 2016年 goappbox. All rights reserved.
//

#import "YMPDFObject.h"

@interface YMPDFObject ()
{
    NSMutableArray *objectArray;
    NSMutableDictionary *objectDictionary;
}
@property (nonatomic, strong) NSString *key;
@property (nonatomic, assign) CGPDFObjectType type;

@property (nonatomic, strong) NSString *string;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) UIImage *image;

@property (nonatomic, assign) BOOL boolValue;
@property (nonatomic, assign) BOOL realValue;
@property (nonatomic, assign) BOOL integerValue;

@property (nonatomic, assign) BOOL isNull;
@end

static void parsePDFObjectApply(const char *key, CGPDFObjectRef object, void *info) {
    YMPDFObject *obj = (__bridge YMPDFObject *)info;
    [obj appliedToPDFObject:object forKey:[NSString stringWithUTF8String:key]];
}

@implementation YMPDFObject

- (instancetype) initWithDictionary:(CGPDFDictionaryRef)dictionary {
    self = [super init];
    if (self) {
        [self setUp];
        [self applyDictionFunction:dictionary];
    }
    return self;
}

- (instancetype) initWithWithObject:(CGPDFObjectRef)object key:(NSString *)key {
    self = [super init];
    if (self) {
        [self setUp];
        [self appliedToPDFObject:object forKey:key];
    }
    return self;
}

- (void)setUp {
    objectArray = [[NSMutableArray alloc] init];
    objectDictionary = [[NSMutableDictionary alloc] init];
}

- (NSArray *)keyNames {
    return [objectDictionary allKeys];
}

- (NSDictionary *)allObjectDictionary {
    return objectDictionary;
}

- (NSArray *)children {
    return objectArray;
}

- (void)addToChildren:(id)obj {
    [objectArray addObject:obj];
}

- (id)objectForKeyedSubscript:(id)key {
    if (key == nil) {
        return nil;
    }
    return [objectDictionary objectForKey:key];
}

- (void)setObject:(id)object forKeyedSubscript:(id < NSCopying >)aKey {
    if (object == nil || aKey == nil) {
        return;
    }
    [objectDictionary setObject:object forKey:aKey];
}

- (void)setObject:(id)anObject atIndexedSubscript:(NSUInteger)index {
    
}
- (id)objectAtIndexedSubscript:(NSUInteger)idx {
    return nil;
}

- (void)appliedToPDFObject:(CGPDFObjectRef)object forKey:(NSString *)key {
    YMPDFObject *obj = [[YMPDFObject alloc] initWithWithObject:object key:key];
    [self addToChildren:obj];
}

- (void)appliedAllObject {
    NSLog(@"%s",__PRETTY_FUNCTION__);
}

- (NSString *)description {
    return [NSString stringWithFormat:@"\n[[\ndictionary : \n%@\r\n\r\narray : \n%@]]",[objectDictionary description],[objectArray description]];
}

- (NSDate *)dateFromValue:(CGPDFStringRef)str {
    return CFBridgingRelease(CGPDFStringCopyDate(str));
}

- (NSString *)stringFromValue:(CGPDFStringRef)str {
    return CFBridgingRelease(CGPDFStringCopyTextString(str));
}

- (NSString *)stringFromObject:(CGPDFObjectRef)object {
    CGPDFStringRef string;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeString, &string);
    return [self stringFromValue:string];
}

- (void)parserData:(CGPDFObjectRef)object type:(CGPDFObjectType)type {
    switch (type) {
        case kCGPDFObjectTypeArray:
        {
            [self parserArray:object];
        }
            break;
        case kCGPDFObjectTypeBoolean:
        {
            [self parserBool:object];
        }
            break;
        case kCGPDFObjectTypeDictionary:
        {
            [self parserDictionary:object];
        }
            break;
        case kCGPDFObjectTypeInteger:
        {
            [self parserInteger:object];
        }
            break;
        case kCGPDFObjectTypeName:
        {
            [self parserName:object];
        }
            break;
        case kCGPDFObjectTypeNull:
        {
            [self parserNull:object];
        }
            break;
        case kCGPDFObjectTypeReal:
        {
            [self parserReal:object];
        }
            break;
        case kCGPDFObjectTypeStream:
        {
            [self parserStream:object];
        }
            break;
        case kCGPDFObjectTypeString:
        {
            [self parserString:object];
        }
            break;
        default:
            break;
    }
}

- (void)parserNull:(CGPDFObjectRef)object {
    self.isNull = YES;
}

- (void)parserArray:(CGPDFObjectRef)object {
    CGPDFArrayRef array;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeArray, &array);
    NSInteger count = CGPDFArrayGetCount(array);
    if (count <= 0) {
        return;
    }
    for (NSInteger i = 0; i < count; i++) {
        CGPDFObjectRef tmp_obj;
        CGPDFArrayGetObject(array, i, &tmp_obj);
        NSString *key = [[NSString alloc] initWithFormat:@"%ld", (long)i];
        [self appliedToPDFObject:tmp_obj forKey:key];
    }
}

- (void)parserReal:(CGPDFObjectRef)object {
    CGPDFReal real;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeReal, &real);
    self.realValue = real;
}

- (void)parserBool:(CGPDFObjectRef)object {
    CGPDFBoolean boolean;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeBoolean, &boolean);
    self.boolValue = boolean;
}

- (void)parserInteger:(CGPDFObjectRef)object {
    CGPDFInteger integer;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeReal, &integer);
    self.integerValue = integer;
}

- (void)parserName:(CGPDFObjectRef)object {
    const char *n;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeName, &n);
    if (strlen(n) > 0) {
        self.name = [[NSString alloc] initWithUTF8String:n];
    } else {
        self.name = @"";
    }
}

- (void)parserString:(CGPDFObjectRef)object {
    CGPDFStringRef string;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeString, string);
    self.string = CFBridgingRelease(CGPDFStringCopyTextString(string));
}

- (void)parserDictionary:(CGPDFObjectRef)object {
    CGPDFDictionaryRef dictionary;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeDictionary, &dictionary);
    [self applyDictionFunction:dictionary];
}

- (void)parserStream:(CGPDFObjectRef)object {
    CGPDFStreamRef stream;
    CGPDFObjectGetValue(object, kCGPDFObjectTypeStream, &stream);
    CGPDFDataFormat format;
    NSData *data = CFBridgingRelease(CGPDFStreamCopyData(stream, &format));
    if (CGPDFDataFormatRaw != format) {
        [self parserImage:data format:format];
    } else {
        [self applyDictionFunction:CGPDFStreamGetDictionary(stream)];
    }
}

- (void)parserImage:(NSData *)data format:(CGPDFDataFormat)format {
    self.image = [UIImage imageWithData:data];
}

- (void)applyDictionFunction:(CGPDFDictionaryRef)dictionary {
    if (dictionary == NULL || CGPDFDictionaryGetCount(dictionary) <= 0) {
        return;
    }
    CGPDFDictionaryApplyFunction(dictionary, &parsePDFObjectApply, (void *)self);
    [self appliedAllObject];
}

@end
